package org.hidaron.asyncdownloader.download;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.hidaron.asyncdownloader.download.listener.OnDownloadListener;

import android.os.Environment;
import android.util.Log;

/**
 * 
 * @author hidaron <hidaron@163.com>
 * 
 */
public class FileDownloader implements Downloader {
	private static final String TAG = FileDownloader.class.getSimpleName();
	private File mTemporaryFile;
	private DownloaderOptions mOption;
	private DownloaderInfo mInfo;
	protected OnDownloadListener mListener;
	private DownloadAsyncHttpClient mClient;
	private DownloadAsyncHttpResponseHandler mDownloadAsyncHttpResponseHandler;

	public FileDownloader(String url, DownloaderOptions options) {
		mOption = options;
		mInfo = new DownloaderInfo();
		mInfo.entityInfo.setEntityPath(url);
		mTemporaryFile = createTemporaryFile();
		mClient = new DownloadAsyncHttpClient();
		mClient.setThreadPool(new ThreadPoolExecutor(0, 5, 0L,
				TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
	}

	@Override
	public void setOnDownloadListener(OnDownloadListener onDownloadListener) {
		mListener = onDownloadListener;
	}

	@Override
	public OnDownloadListener getOnDownloadListener() {
		return mListener;
	}

	@Override
	public void download() {
		mDownloadAsyncHttpResponseHandler = new DownloadAsyncHttpResponseHandler(
				this);
		mClient.get(getFileUrl(), mDownloadAsyncHttpResponseHandler);
	}

	@Override
	public void redownload() {
		Header[] headers = new Header[] { new BasicHeader("RANGE",
				String.format("bytes=%d-", mInfo.getEntityInfo()
						.getWrittenBytesLength())) };
		Log.d(TAG,
				"reDownload content length "
						+ String.valueOf(mInfo.getEntityInfo()
								.getWrittenBytesLength()));

		if (null == mDownloadAsyncHttpResponseHandler) {
			mDownloadAsyncHttpResponseHandler = new DownloadAsyncHttpResponseHandler(
					this);
		}
		mClient.get(getFileUrl(), headers, mDownloadAsyncHttpResponseHandler);
	}

	@Override
	public void pause() {
		Log.d(TAG, "pause true");
		mDownloadAsyncHttpResponseHandler.setPause(true);
	}

	@Override
	public void cancel() {
		Log.d(TAG, "cancel true");
		mDownloadAsyncHttpResponseHandler.setCanceled(true);
	}

	protected String getTemporaryPrefix() {
		return mOption.getFileNameGreator().greateName(getFileUrl());
	}

	protected String getTemporarySuffix() {
		if (null == getFileUrl()) {
			return null;
		}
		String suffix = null;
		try {
			String fileName = new URL(getFileUrl()).getFile();
			if (null != fileName) {
				suffix = fileName.substring(fileName.lastIndexOf("."));
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return suffix;
	}

	@Override
	public File getTemporaryFile() {
		return mTemporaryFile;
	}

	private File createTemporaryFile() {
		File tempFile = null;
		try {
			if (null == mOption.getDownloadsDir()) {
				tempFile = Environment.getDownloadCacheDirectory();
			} else {
				tempFile = mOption.getDownloadsDir();
			}
			if (!tempFile.exists()) {
				if (!tempFile.mkdirs()) {
					throw new IOException();
				}
			}
			return File.createTempFile(getTemporaryPrefix(),
					getTemporarySuffix(), tempFile);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public boolean deleteTemporaryFile() {
		return mTemporaryFile == null ? false : mTemporaryFile.delete();
	}

	@Override
	public String getFileUrl() {
		return mInfo.getEntityInfo().getEntityPath();
	}

	public DownloadStatus getDownloadStatus() {
		return mInfo.getStatus();
	}

	@Override
	public void setDownloadStatus(DownloadStatus status) {
		if (null != status) {
			mInfo.setStatus(status);
		}
	}

	@Override
	public DownloaderInfo getInfo() {
		return mInfo;
	}

}
